import EventKeys from "@enu/eventKeys.js";
import inputFilterRegx from "@utils/inputFilterRegx.js";
import {
    splitStringToArray,
    getElementIndexOnParent,
    labelStringRemoveLabelExceptImg,
    wrapStringSingleItem,
} from "@utils/tools.js";
import {
    getBoundingClientRect,
    getDomToVisbleDis
} from "in-view-utils";
import { copyEventListener } from "@utils/copyPaste.js";
import { cursorStr, moveToFn, moveTo } from "@utils/cursor.js";
import { directive as disabledBodyScroll } from "disable-body-scroll";
import { setCurrInput } from "@devass/js/blur.js";
import BaseMixins from "../../../mixins/base";

import {
    isInDomView
} from "in-view-utils";
import {
    updateHtmlArr,
    getStartAndEndIndex,
    removeAllRanges,
} from "@devass/js/range.js"; //监听原生用户选中文字
import propsConfig from "@comp/input/propsConfig.js";
export default {
    name: "keyboardInput",
    directives: {
        "disabled-body-scroll": disabledBodyScroll,
    },
    mixins: [BaseMixins],

    props: propsConfig["defaultInput"],
    model: {
        prop: "value",
        event: "change",
    },
    data() {
        return {
            isFocus: false, //获取焦点，可输入的状态
            valueArr: [], //已填入的字符串转数组
            cursorIndex: null, //当前光标的位置，也就是下一次输入内容插入的位置
            blurMethods: null, //点击document失去焦点事件
            scrollLeft: 0, //容器滚动X距离，只记录程序导致的，用户导致的忽略
            scrollTop: 0, //容器滚动的Y距离，只记录程序导致的，用户导致的忽略
            fixedInputWrap: { position: "fixed" },
        };
    },
    computed: {
        //最终的键盘额外参数
        keyBoardOtherPropsEnd() {
            // return this.keyBoardOtherProps ? this.keyBoardOtherProps : {};
        },
        inputWrapStyle() {
            console.log("this.height", this.height, this.height != -1);
            if (this.height != -1 && !isNaN(parseInt(this.height))) {
                if (/(px)$/.test(this.height)) {
                    return {
                        height: this.height,
                        display: "block",
                    };
                } else {
                    return {
                        height: parseFloat(this.height) + "px",
                        display: "block",
                    };
                }
            } else if (this.height != -1) {
                console.warn("erro props  height of input");
            }
        },
        // inputId() {
        //     let tString = new Date().getTime();
        //     return `input-id-${tString}-${uuid()}`;
        // },
        //已输出的结果展示值（输入框里面的字符串）
        tmpValue() {
            let t = "";
            this.valueArr.forEach((e) => {
                t += e;
            });

            return t;
        },
        tmpValueNoFlash() {
            let t = "";
            let tmpArray = this.valueArr.filter((item) => item != cursorStr);
            tmpArray.forEach((e) => {
                e = labelStringRemoveLabelExceptImg(e); //移除普通文本包裹的标签
                t += e;
            });
            return t;
        },
        //同步给外层事件的值，input blur focus
        eventParams() {
            return {
                value: this.tmpValueNoFlash,
                el: this.$refs["vueKeyboardInput"],
            };
        },
        disabledScrollDirectiveStatus() {
            return this.allowEnter ? "working" : "disabled";
        },
    },
    watch: {
        value: {
            handler(newV, oldV) {
                console.log("value变了", newV);
                let t = splitStringToArray("" + newV, this.allowEnter);
                let labelIndex = this.valueArr.findIndex((item) => item == cursorStr);
                if (this.isFocus) {
                    if (labelIndex == -1) {
                        console.log("input:没有贯标了?");
                        t.push(cursorStr);
                        this.valueArr = t;
                        this.cursorIndex = this.valueArr.length - 1;
                    } else {
                        //处理输入框close按钮删除
                        if (String(newV).length == 0) {
                            this.cursorIndex = 0;
                            this.valueArr = t;
                            this.valueArr.splice(this.cursorIndex, 0, cursorStr); //必须要追加光标
                        } else {
                            //修复bug:数据类型，并且用了插槽 累-1或累+1时候，光标没有位移到最后
                            //这里添加相差值为1，是因为用户可以点击字符串中间某个值来直接修改
                            if (
                                (this.type === "int" || this.type === "float") &&
                                Math.abs(newV - oldV) == 1
                            ) {
                                t.push(cursorStr);
                                this.valueArr = t;
                            } else {
                                console.log("input:追加贯标了？");
                                this.valueArr = t;
                                this.valueArr.splice(this.cursorIndex, 0, cursorStr); //必须要追加光标
                            }
                        }
                    }
                } else if (!this.isFocus) {
                    this.valueArr = t;
                    this.cursorIndex = this.valueArr.length;
                    console.log("input:失去焦点了");
                }

                /*
                 * 向所有组件推送，最新值
                 *1.光标控制面板，复制需要用到
                 */
                this.$root.$emit(EventKeys["vue-keyboard-cn-update-value"], "" + newV);
                //输入时候内容滚到指定位置
                this.$nextTick(() => {
                    // this.inputDomInnerScroll();
                    this.inputWillblur(); //失去全选
                });
            },
            immediate: true,
        },
        isFocus(newV) {
            if (newV) {
                //如果用户已经存在光标，就特殊处理，因为isFocus是异步触发的，所以这里需要特殊处理
                //否则会出现点击了内部元素，结果等isFocus事件执行时候，把光标挪到了最后面了
                if (this.valueArr.indexOf(cursorStr) > -1) {
                    return;
                }
                if (!this.allowEnter) {
                    this.valueArr = splitStringToArray(this.value, this.allowEnter);

                    this.valueArr.push(cursorStr);
                    this.cursorIndex = this.valueArr.length - 1;
                }
            } else {
                this.valueArr = this.valueArr.filter((item) => item != cursorStr);
            }
        },
        tmpValue() {
            this.$nextTick(() => {
                this.isFocus && this.inputDomInnerScroll();
            });
        },
        valueArr: {
            immediate: true,
            handler(newV) {
                //更新用户选择对象里面的数组
                updateHtmlArr(newV);
            },
        },
    },
    created() {
        //监听原生复制事件
        copyEventListener(this);
        this.addRootEventLister();
        this.selectAllBlur();
    },
    beforeDestroy() {
        document.removeEventListener("click", this.blurMethods);
    },
    methods: {
        clear() {
            this.focus(true);
            this.$emit("change", "");
            this.$emit("input", {
                value: "",
                el: this.$refs["vueKeyboardInput"],
            });
        },
        selectAllBlur() {
            this.blurMethods = this.inputWillblur.bind(this);
            // document.addEventListener("click", this.blurMethods);
        },

        multLineScroll() {
            //可滚动容器
            let scrollWrapBox = this.$refs['wrapvueKeyboardInput'];
            let scrollBox = this.$refs["vueKeyboardInputScrollBox"];
            let domFlash = scrollBox.querySelector(".key-board-flash");
            if (scrollBox && domFlash) {
                let dis = getDomToVisbleDis({ dom: domFlash, viewPort: scrollWrapBox, rotate: this.rotate })
                scrollBox.scrollBy(dis.x, dis.y);
                console.log("dis", dis, this.rotate)
            }


            let scrollBoxFixed = this.$refs["vue-keyboard-input-fixed-wrap"];
            //固定键盘顶部的输入框不一定存在
            if (scrollBoxFixed) {
                let domFlashFixed = scrollBoxFixed.querySelector(".key-board-flash");
                if (scrollBoxFixed && domFlashFixed) {
                    let dis = getDomToVisbleDis({ dom: domFlashFixed, viewPort: scrollBoxFixed, rotate: this.rotate })
                    scrollBoxFixed.scrollBy(dis.x, dis.y);
                }
            }

        },
        onlineScroll() {
            //可滚动容器
            let scrollBox = this.$refs["vueKeyboardInput"];
            let domFlash = scrollBox.querySelector(".key-board-flash");
            if (scrollBox && domFlash) {
                let dis = getDomToVisbleDis({ dom: domFlash, viewPort: scrollBox, rotate: this.rotate })
                scrollBox.scrollBy(dis.x, dis.y);
            }
            //固定输入框==
            let scrollBoxFixed = this.$refs["vueKeyboardInputFixed"];
            //固定键盘顶部的输入框不一定存在
            if (scrollBoxFixed) {
                let domFlashFixed = scrollBoxFixed.querySelector(".key-board-flash");
                if (scrollBoxFixed && domFlashFixed) {
                    let fixedDis = getDomToVisbleDis({ dom: domFlashFixed, viewPort: scrollBoxFixed, rotate: this.rotate })
                    scrollBoxFixed.scrollBy(fixedDis.x, fixedDis.y);
                }
            }

        },
        inputDomInnerScroll() {
            //多行和单行，滚动元素不一样，所以分开写，不要互相干扰
            if (this.allowEnter) {
                this.multLineScroll();
            }
            else {
                this.onlineScroll();
            }
        },
        select() {
            this.$refs["input"].classList.add("vue-keyboard-input-text-focus");
            this.$refs["input"].focus();
        },
        unSelect() {
            try {
                //PasswordInput键盘会报错
                this.$refs["input"].blur();
                this.$refs["input"].classList.remove("vue-keyboard-input-text-focus");
            } catch (e) { }
        },
        addRootEventLister() {
            //全选按钮
            this.$root.$on(EventKeys["vue-keyboard-cn-select-all"], () => {
                if (!this.isFocus || !this.$refs["input"]) {
                    return;
                }
                if (
                    this.$refs["input"].classList.contains(
                        "vue-keyboard-input-text-focus"
                    )
                ) {
                    this.unSelect();
                } else {
                    this.select();
                }
            });
            //监听键盘已显示，或已隐藏
            this.$root.$on(EventKeys["vue-keyboard-cn-showed"], (data) => {
                if (data.el && data.show) {
                    this.fixedInputWrap = {};
                    let computedStyle = window.getComputedStyle(data.el);
                    let height = computedStyle["height"];
                    let width = computedStyle["width"];
                    this.fixedInputWrap = {
                        position: "fixed",
                        left: 0,
                        bottom: height,
                        width: width,
                    };
                }
            });
            //监听方向
            this.$root.$on(EventKeys["vue-keyboard-cn-cursor-move"], (str) => {
                if (!this.isFocus) {
                    return;
                }
                let movedData = moveToFn(this.valueArr, str);
                if (Array.isArray(movedData.arr)) {
                    this.valueArr = movedData.arr;
                    this.cursorIndex = movedData.index;
                }
            });
            //其他input触发获取焦点时候，本input失去焦点
            this.$root.$on(EventKeys["vue-keyboard-cn-focus"], (data) => {
                let isCurrFocus = this.mixins_isCurrFocus();
                if (!isCurrFocus && this.isFocus) {
                    this.isFocus = false;
                    this.$emit("blur", this.eventParams);
                } else if (isCurrFocus) {
                    this.isFocus = true;
                    this.$emit("focus", this.eventParams);
                }
            });
        },
        deleteHandler() {
            console.log("input:delete");
            if (!this.isFocus) {
                return;
            }
            let { start, end, collapsed } = getStartAndEndIndex();

            if (start != -1 && end != -1 && !collapsed) {
                let deleteLength = end - start > 0 ? end - start + 1 : 1;
                this.deleteFn(start, deleteLength);
                return;
            } else if (this.currInputIsSelected()) {
                //全选状态下输入
                this.replaceAllWith("");
                return;
            }
            this.deleteFn();
        },
        /**
         * 
         * @param {*} textOrObj  是普通字符串，或者一个对象{txt:"",index:-1} //-1代表贯标往前走一个位置
         * @returns 
         */
        appendHandler(textOrObj) {
            let text = "";
            let index = 0;//代表光标不需要特殊处理
            if (typeof textOrObj == 'object' && textOrObj.txt) {
                text = String(textOrObj.txt);
                if (!isNaN(Number(textOrObj.index))) {
                    index = textOrObj.index;
                }

            } else {
                text = String(textOrObj);
            }
            if (!this.isFocus) {
                return false;
            }
            if (!text) {
                return false;
            }

            //可以输入后再判断处理============================
            //全选状态下输入
            //只校验输入的内容，不校验已存在的内容
            console.log(
                "input :this.currInputIsSelected()",
                this.currInputIsSelected()
            );
            if (this.currInputIsSelected() && this.canPushItem(text, false)) {
                this.replaceAllWith(text);
                this.removeSelected();
                return;
            } else if (!this.canPushItem(text)) {
                return;
            }
            if (text === " ") {
                this.appendItem(wrapStringSingleItem(text));
            } else if (text === "\r\n") {
                if (this.allowEnter) {
                    this.appendItem("<br/>");
                } else {
                    this.$emit("submit", {
                        value: this.value,
                        el: this.$refs["vueKeyboardInput"],
                    });
                }
            } else {
                let textArray = splitStringToArray(text, this.allowEnter); //分割内容为数组
                textArray.forEach((item) => this.appendItem(item));
                if (index) {
                    this.cursorIndex = this.cursorIndex + index;
                }
            }
        },
        //是否可以添加内容，根据type来处理
        //mix(所有）int(整数)，float(小数) zh,cn //展示键盘输入方式，默认中文，和键盘相对应
        /**
         * includeCurrTxt 正则判断是否包括已存在的内容，默认是
         */
        canPushItem(text, includeCurrTxt = true) {
            let returnValue = false;
            let endText = `${this.value}${text}`;
            if (!includeCurrTxt) {
                endText = String(`${text}`);
            }
            if (!isNaN(Number(this.maxLength)) &&
                this.maxLength > 0 &&
                endText.length > this.maxLength
            ) {
                return;
            }
            if (this.regx) {
                return new RegExp(this.regx).test(text);
            }
            switch (this.type) {
                case "float":
                    returnValue = inputFilterRegx.float(endText, this.decimal);
                    break;
                case "int":
                    returnValue = inputFilterRegx.int(endText);
                    break;
                case "cn":
                    returnValue = inputFilterRegx.cn(endText);
                    break;
                case "en":
                    returnValue = inputFilterRegx.en(endText);
                    break;
                default:
                    returnValue = true;
                    break;
            }
            console.log("input:returnValue", returnValue);
            return returnValue;
        },
        inputWillblur(e) {
            if (!this.isFocus) {
                return;
            }
            var inputs = document.querySelectorAll(".vue-keyboard-input-text-focus");
            for (let i = 0; i < inputs.length; i++) {
                inputs[i].classList.remove("vue-keyboard-input-text-focus");
            }
        },
        replaceAllWith(val) {
            this.$emit("change", val); //v-model同步数据
            this.$emit("input", {
                value: val,
                el: this.$refs["vueKeyboardInput"],
            });
        },
        currInputRemoveSelectedClass() {
            if (this.currInputIsSelected()) {
                this.$refs["input"].classList.remove("vue-keyboard-input-text-focus");
            }
        },
        currInputIsSelected() {
            return this.$refs["input"].classList.contains(
                "vue-keyboard-input-text-focus"
            );
        },
        removeSelected() {
            this.$refs["input"].classList.remove("vue-keyboard-input-text-focus");
        },
        getClickElement(e, wrapDiv) {
            removeAllRanges();
            if (this.disabled) {
                return;
            }
            //当前如果已经获取焦点，不再出发获取焦点事件
            if (!this.isFocus) {
                this.focus(true);
            }
            //如果点击到的不是子节点，触发空白点击处理
            console.log("target===", e.target, wrapDiv)
            if (e.target
                && e.target.getAttribute
                && wrapDiv
                && e.target.getAttribute("class") == wrapDiv.getAttribute("class")) {
                this.allowEnterBoxClickEmptyArea(e, this.$refs['vueKeyboardInput']);
                console.log("点击的是父容器")
                return;
            }
            if (
                e.target &&
                e.target.classList &&
                e.target.classList.contains("vue-keyboard-input-text")
            ) {
                return;
            }
            let index = getElementIndexOnParent(e.target);
            let movedData = moveTo(this.valueArr, index);
            if (Array.isArray(movedData.arr)) {
                this.valueArr = movedData.arr;
                this.cursorIndex = movedData.index;
            }
        },
        appendItem(text = "") {
            if (!text) {
                return;
            }
            //光标处插入文字
            this.valueArr.splice(this.cursorIndex, 0, text);
            this.cursorIndex = this.cursorIndex + 1;
            //修复光标
            let tmpArray = this.valueArr.filter((item) => item != cursorStr);
            tmpArray.splice(this.cursorIndex, 0, cursorStr);
            this.valueArr = tmpArray;
            this.$emit("change", this.tmpValueNoFlash); //v-model同步数据
            this.$emit("input", this.eventParams);
        },
        deleteFn(startIndex = this.cursorIndex - 1, deleteLength = 1) {
            //如果是密码输入框
            if (this.type === "PasswordInput") {
                this.$mix_passwordInput_delete();
                return;
            }
            if (this.cursorIndex <= 0) {
                this.cursorIndex = 0;
                return;
            }
            //删掉光标前一个字符串
            this.valueArr.splice(startIndex, deleteLength);
            //如果贯标在删除的字段内，需要把光标补回来
            if (
                startIndex &&
                (this.cursorIndex >= startIndex ||
                    this.cursorIndex <= startIndex + deleteLength)
            ) {
                this.valueArr.splice(startIndex, 0, cursorStr);
            }
            //修复光标的坐标
            this.cursorIndex = startIndex;
            this.$emit("change", this.tmpValueNoFlash); //同步给外层
            this.$emit("input", this.eventParams);
        },
        focus(bool = false) {
            if (this.disabled) {
                return;
            }

            this.isFocus = bool;

            //这里了需要放到nextTick里面是因为 this.$refs['fixedInputWrapBox']被v-if控制
            // console.log("this.refs", this.$refs['fixedInputWrapBox'])
            setCurrInput({
                vm: this,
                dom: this.$refs["wrapvueKeyboardInput"] ?
                    this.$refs["wrapvueKeyboardInput"] :
                    this.$refs["input"].$el,
                fixedInput: this.$refs['fixedInputWrapBox']
            });
            let obj = {
                isFocus: bool,
                value: this.valueArr,
                tmpValueNoFlash: this.tmpValueNoFlash,
                type: this.type,
                keyBoardOtherProps: this.keyBoardOtherProps, //NumberKeyboard专用
                inputOtherProps: this.inputOtherProps, //输入框额外参数
                canSwitchOtherBoard: this.canSwitchOtherBoard,
                // inputId: this.inputId,
                inputLang: this.inputLang,
                allowEnter: this.allowEnter,
                keyBoardProps: this.keyBoardProps,
                inputProps: this.inputProps,
            };
            if (this.keyBoard) {
                this.keyBoard.getInputInfo = obj;
                this.keyBoard.show = true;
            } else {
                this.$root.$emit(EventKeys["vue-keyboard-cn-focus"], obj);
            }
        },
        allowEnterBoxClickEmptyArea(e, wrapBox) {
            this.focus(true);
            if (this.disabled) {
                return;
            }
            let spanItem = wrapBox.querySelectorAll(
                ".vue-keyboard-text-item"
            );
            let lastSpanItem;
            let firstItem = spanItem[0];
            let rectj = getBoundingClientRect(firstItem).top;
            // console.log("rect------", e.clientY, "top", rectj)
            for (let i = 0; i < spanItem.length; i++) {
                let currItem = spanItem[i];
                let rectObj = getBoundingClientRect(currItem);
                if (this.rotate === 90 || this.rotate === -90) {
                    let clientX = e.clientX;
                    let right = rectObj.right;
                    let left = rectObj.left;
                    let isInViewVisible = isInDomView({
                        dom: currItem,
                        wrapDom: wrapBox,
                        rotate: this.rotate
                    })
                    if (clientX >= left && clientX <= right && isInViewVisible) {
                        lastSpanItem = currItem;
                    }
                } else {
                    let clientY = e.clientY;
                    console.log("e", e)
                    let top = rectObj.top;
                    let bottom = rectObj.bottom;
                    let isInViewVisible = isInDomView({
                        dom: currItem,
                        wrapDom: wrapBox,
                        rotate: this.rotate
                    })
                    if (clientY >= top && clientY <= bottom && isInViewVisible) {
                        lastSpanItem = currItem;
                    }
                }
            }
            if (lastSpanItem) {
                //光标的位置要比内容元素大1
                let index = getElementIndexOnParent(lastSpanItem) + 1;
                let movedData = moveTo(this.valueArr, index);
                if (Array.isArray(movedData.arr)) {
                    this.valueArr = movedData.arr;
                }
            }
        },
    },
};